package com.gulimall.product.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.common.utils.PageUtils;
import com.common.utils.Query;
import com.gulimall.product.dao.CategoryDao;
import com.gulimall.product.entity.CategoryEntity;
import com.gulimall.product.service.CategoryBrandRelationService;
import com.gulimall.product.service.CategoryService;
import com.gulimall.product.vo.CataAjaxVo2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


@Service("categoryService")
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService {

    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Autowired
    CategoryBrandRelationService categoryBrandRelationService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<CategoryEntity> page = this.page(
                new Query<CategoryEntity>().getPage(params),
                new QueryWrapper<CategoryEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public List<CategoryEntity> listWithTree() {
        //1.查出所有分类  TODO 综合1
        List<CategoryEntity> list = baseMapper.selectList(null);
        //2.组装成父子的树形结构
        //2.1找到所有的一级分类
        List<CategoryEntity> level1list = list.stream().filter((categoryEntity) -> {
            return categoryEntity.getParentCid() == 0;
        }).map((menu) -> {
            menu.setChildren(getChildrens(menu, list));             //将每个对象的Children属性改变返回
            return menu;
        }).sorted((menu1, menu2) -> {
            return (menu1.getSort() == null ? 0 : menu1.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort());
        }).collect(Collectors.toList());            //获取id为0的所有元素
//        System.out.println(level1list);
        return level1list;
    }

    //递归查找所有子菜单
    public List<CategoryEntity> getChildrens(CategoryEntity categoryEntity, List<CategoryEntity> list) {
        List<CategoryEntity> childrens = list.stream().filter(categoryEntity1 -> categoryEntity1.getParentCid() == categoryEntity.getCatId())
                .map(categoryEntity1 -> {
                    categoryEntity1.setChildren(getChildrens(categoryEntity1, list));
                    return categoryEntity1;
                }).sorted((menu1, menu2) -> (menu1.getSort() == null ? 0 : menu1.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort()))
                .collect(Collectors.toList());
        return childrens;
    }

    @Override
    public void removeMenuByIds(List<Long> longs) {
        baseMapper.deleteBatchIds(longs);
    }

    //找出对应的种类阶梯
    @Override
    public Long[] findCatelogPath(Long catelogId) {
        CategoryEntity categoryEntity = this.getById(catelogId);
        List<Long> list = new ArrayList<>();
        while (categoryEntity != null && categoryEntity.getParentCid() != null) {
            Long parentCid = categoryEntity.getParentCid();
            list.add(parentCid);
            categoryEntity = this.getById(parentCid);
        }
        Collections.reverse(list);
        return list.toArray(new Long[list.size()]);
    }

    @Transactional
    @Override
    public void updateDetailsById(CategoryEntity category) {
        this.updateById(category);
        //更新其他冗余字段
        categoryBrandRelationService.updateCategory(category.getCatId(), category.getName());
    }

    @Override
    public List<CategoryEntity> getAllParentList() {
        List<CategoryEntity> categoryEntityList = this.baseMapper.selectList(new QueryWrapper<CategoryEntity>().eq("parent_cid", 0));
        return categoryEntityList;
    }

    @Override
    public Map<Long, List<CataAjaxVo2>> getAjaxCateTree() {
        String categoryAjax = stringRedisTemplate.opsForValue().get("categoryAjax");
        if(StringUtils.isEmpty(categoryAjax)){
            Map<Long, List<CataAjaxVo2>> ajaxCateTreeByDB = getAjaxCateTreeByDB();
            return ajaxCateTreeByDB;
        }else{
            //json字符串转回对象
            Map<Long, List<CataAjaxVo2>> result = JSON.parseObject(categoryAjax, new TypeReference<Map<Long, List<CataAjaxVo2>>>() {});
            return result;
        }

    }


    //获取首页鼠标放置的二级菜单的ajax请求
    public synchronized Map<Long, List<CataAjaxVo2>> getAjaxCateTreeByDB() {
        String categoryAjax = stringRedisTemplate.opsForValue().get("categoryAjax");
        if(StringUtils.isEmpty(categoryAjax)) {
            List<CategoryEntity> selectList = baseMapper.selectList(null);

            //获取所有的一级分类
            List<CategoryEntity> parentList = getParent_cid(selectList, 0L);
            Map<Long, List<CataAjaxVo2>> map = parentList.stream().collect(Collectors.toMap(k -> k.getCatId(), v -> {

                //获取二级分类
                List<CategoryEntity> categoryEntities2 = getParent_cid(selectList, v.getCatId());
                if (categoryEntities2.size() != 0) {
                    List<CataAjaxVo2> cataAjaxVo2List = categoryEntities2.stream().map(categoryEntity2 -> {
                        //获取三级分类
                        List<CategoryEntity> categoryEntityList3 = getParent_cid(selectList, categoryEntity2.getCatId());

                        List<CataAjaxVo2.Catalog3> catalog3List = null;
                        if (categoryEntityList3.size() != 0) {
                            catalog3List = categoryEntityList3.stream().map(categoryEntity3 -> {
                                CataAjaxVo2.Catalog3 catalog3 = new CataAjaxVo2.Catalog3(categoryEntity3.getParentCid(), categoryEntity3.getCatId(), categoryEntity3.getName());
                                return catalog3;
                            }).collect(Collectors.toList());
                        }
                        CataAjaxVo2 vo = new CataAjaxVo2(categoryEntity2.getParentCid(), catalog3List, categoryEntity2.getCatId(), categoryEntity2.getName());
                        return vo;
                    }).collect(Collectors.toList());
                    return cataAjaxVo2List;
                }
                return null;
            }));

            //为了防止缓存穿透，如果结果为null，就设置一个0
            //为了防止缓存雪崩，设置一个随机的过期时间，这里暂时不考虑缓存雪崩的情况
            //为了防止缓存击穿，加一个锁
            //转换为json字符串保存
            System.out.println("没有查询数据库，从缓存中获取");
            stringRedisTemplate.opsForValue().set("categoryAjax", JSON.toJSONString(map), 1, TimeUnit.DAYS);
            return map;
        }
        Map<Long, List<CataAjaxVo2>> result = JSON.parseObject(categoryAjax, new TypeReference<Map<Long, List<CataAjaxVo2>>>() {});
        return result;
    }

    private List<CategoryEntity> getParent_cid(List<CategoryEntity> list,Long parent_cid) {
//        return baseMapper.selectList(new QueryWrapper<CategoryEntity>().eq("parent_cid", categoryEntity2.getCatId()));
        List<CategoryEntity> entityList = list.stream().filter(categoryEntity -> parent_cid == categoryEntity.getParentCid()).collect(Collectors.toList());
        return entityList;
    }

}